/*=========================================================================

Program:   Virtual Surgery
Language:  C++
Date:      2009-9-1
Version:   0.1
Mail:		   nelfylee@gmail.com

Copyright (c) 2009 Nelfy Lee. All rights reserved.

=========================================================================*/
#ifndef _SMOOTHING_PANELS_H_
#define _SMOOTHING_PANELS_H_

#include "ui_SmoothingPanel.h"
#include "SmoothingThreads.h"

#include "ControlPanelBase.h"
#include "ControlPanelDock.h"

#include <QFrame>
#include <QDebug>


class SmoothingPanel : public ControlPanelBase, public Ui::SmoothingPanel
{
	Q_OBJECT
public:
	SmoothingPanel(QWidget *parent):ControlPanelBase(parent)
	{
		setupUi(this);
		m_panelType = ptSmoothing;

		connect(btn_smoothApply, SIGNAL(clicked()), SLOT(slotSmoothApply()));
		connect(btn_morphApply, SIGNAL(clicked()), SLOT(slotMorphApply()));
	}


private slots:

	void slotSmoothApply()
	{
		Source *source = currentSource();
		if ( !source)
			return;

		if ( source->type() != stVolume)
		{
			qDebug() << "[CF]: Source is not a Volume";
			return;
		}

		int smoothType = cb_smoothType->currentIndex();
		int smoothLevel = cb_smoothLevel->currentIndex();

		if ( smoothType == 0) // vessel smoothing
		{
			return CFSmoothing(source, smoothLevel);
		}
		else if ( smoothType == 1) // liver smoothing
		{
			return CADSmoothing(source, smoothLevel);
		}
		else if ( smoothType == 2) // post smoothing
		{
			return AABSmoothing(source, smoothLevel);
		}
	}


	void slotMorphApply()
	{
		Source *source = currentSource();
		if ( !source)
			return;

		if ( source->type() != stVolume)
		{
			qDebug() << "[CF]: Source is not a Volume";
			return;
		}

		int m_radius = spin_radius->value();
		if ( m_radius <=0 )
			return;

		switch(source->dataType())
		{
		case VTK_UNSIGNED_CHAR:
			{
				createMorphingThread<unsigned char>();
				break;
			}
		case VTK_SHORT:
			{
				createMorphingThread<short>();
				break;
			}
		case VTK_FLOAT:
			{
				createMorphingThread<float>();
				break;
			}
		default:
			return;
		}
	}

private:
	void CFSmoothing(Source *source, int smoothLevel)
	{
		FilteringThreadBase *thread;

		switch(source->dataType())
		{
		case VTK_SHORT:
			{
				thread = new ItkCurvatureFlowThread<ImageShort3D>(source, smoothLevel);
				break;
			}
		case VTK_FLOAT:
			{
				thread = new ItkCurvatureFlowThread<ImageFloat3D>(source, smoothLevel);
				break;
			}
		default:
			return;
		}

		connect(thread, SIGNAL(emitProgressStart(QString)), m_parent, SLOT(slotProgressStart(QString)));
		connect(thread, SIGNAL(emitProgressUpdate(int)), m_parent, SLOT(slotProgressUpdate(int)));
		connect(thread, SIGNAL(emitProgressDone()), m_parent, SLOT(slotProgressDone()));

		thread->start();
	}


	void CADSmoothing(Source *source, int smoothLevel)
	{
		FilteringThreadBase *thread;

		switch(source->dataType())
		{
		case VTK_SHORT:
			{
				thread = new ItkCurvatureAnisotropicDiffusionThread<ImageShort3D>(source, smoothLevel);
				break;
			}
		case VTK_FLOAT:
			{
				thread = new ItkCurvatureAnisotropicDiffusionThread<ImageFloat3D>(source, smoothLevel);
				break;
			}
		default:
			return;
		}

		connect(thread, SIGNAL(emitProgressStart(QString)), m_parent, SLOT(slotProgressStart(QString)));
		connect(thread, SIGNAL(emitProgressUpdate(int)), m_parent, SLOT(slotProgressUpdate(int)));
		connect(thread, SIGNAL(emitProgressDone()), m_parent, SLOT(slotProgressDone()));

		thread->start();
	}



	void AABSmoothing(Source *source, int smoothLevel)
	{
		FilteringThreadBase *thread;

		switch(source->dataType())
		{
		case VTK_SHORT:
			{
				thread = new ItkAntiAliasBinaryThread<ImageShort3D>(source, smoothLevel);
				break;
			}
		case VTK_UNSIGNED_CHAR:
			{
				thread = new ItkAntiAliasBinaryThread<ImageUChar3D>(source, smoothLevel);
				break;
			}
		case VTK_FLOAT:
			{
				thread = new ItkAntiAliasBinaryThread<ImageFloat3D>(source, smoothLevel);
				break;
			}
		default:
			return;
		}

		connect(thread, SIGNAL(emitProgressStart(QString)), m_parent, SLOT(slotProgressStart(QString)));
		connect(thread, SIGNAL(emitProgressUpdate(int)), m_parent, SLOT(slotProgressUpdate(int)));
		connect(thread, SIGNAL(emitProgressDone()), m_parent, SLOT(slotProgressDone()));

		thread->start();
	}





// 	virtual void slotFillHoleApply()
// 	{
// 		if ( !m_source || m_source->type() != stVolume )
// 		{
// 			qDebug() << "[CF]: Source is not a Volume";
// 			return;
// 		}
// 
// 		switch(m_source->dataType())
// 		{
// 		case VTK_SHORT:
// 			{
// 				createFillHoleThread<short>();
// 				break;
// 			}
// 		case VTK_FLOAT:
// 			{
// 				createFillHoleThread<float>();
// 				break;
// 			}
// 		case VTK_UNSIGNED_CHAR:
// 			{
// 				createFillHoleThread<unsigned char>();
// 				break;
// 			}
// 		default:
// 			{
// 				qDebug("[VesselProcessingPanel::segment]: doesn't support current data type [%d]", m_source->dataType());
// 				break;
// 			}
// 		}
// 	}


private:
	template<class FInputPixelType>
	void createMorphingThread()
	{
		typedef itk::Image<FInputPixelType,3> FInputImageType;
		BinaryMorphologicalThread<FInputImageType> * thread =
			new BinaryMorphologicalThread<FInputImageType>(currentSource());

		BinaryMorph mode = (BinaryMorph)cb_morphMode->currentIndex();

		thread->setParameters(mode, spin_foreground->value(), spin_background->value(), spin_radius->value());

		connect(thread, SIGNAL(emitProgressStart(QString)), m_parent, SLOT(slotProgressStart(QString)));
		connect(thread, SIGNAL(emitProgressUpdate(int)), m_parent, SLOT(slotProgressUpdate(int)));
		connect(thread, SIGNAL(emitProgressDone()), m_parent, SLOT(slotProgressDone()));

		thread->start();
	}



// 	template<class FInputPixel>
// 	void createFillHoleThread() 
// 	{
// 		typedef itk::Image<FInputPixel, 3> FInputImage;
// 		ItkFillHoleThread<FInputImage> *thread =  
// 			new ItkFillHoleThread<FInputImage>(m_source);
// 
// 		connect(thread, SIGNAL(emitProgressStart(QString)), m_parent, SLOT(slotProgressStart(QString)));
// 		connect(thread, SIGNAL(emitProgressUpdate(int)), m_parent, SLOT(slotProgressUpdate(int)));
// 		connect(thread, SIGNAL(emitProgressDone()), m_parent, SLOT(slotProgressDone()));
// 
// 		thread->start();
// 	}
};



#endif


